/*
 * process_control.c
 *
 *  Created on: Mar 11, 2014
 *      Author: lifeng
 */

#include <stdio.h>
#include <string.h>

#include <unistd.h>
#include <pthread.h>

#include "serial/frame_manager.h"
#include "serial/frame.h"

#include "lib/hwclock.h"
#include "lib/bcd.h"

#include "lib/block_filter.h"
#include "lib/block_manager.h"

#include "storage/record_manager.h"

#include "led/led.h"
#include "sound/sound.h"

#include "config/config.h"
#include "config/cab_type.h"

#include "global.h"

#include "./state/state.h"
#include "./battery/battery.h"
#include "WatchDog/WatchDog.h"

pthread_t thread_control;

//const char version[16] = "Vt.e.st-16/10/18";
//const char version[16] = "V2.1.02-16/12/12";
//const char version[16] = "V2.1.01-17/05/12";
//const char version[16] = "V2.1.02-17/10/04";
//const char version[16] = "V2.1.03-18/11/02";
const char version[16] = "V2.2.01-19/02/01";
const int NOTRECICTTIMEMAX = 8;
static int notReciveTimeCount = 0;
typedef void (*cirframe_process_handler)(char dest_addr, char src_addr,
		char operation, char cmd, char * frameData, int frameDataLen);

cirframe_process_handler record_process_handler_table[256];

static void set_cir_time(char dest_addr, char src_addr, char operation,
		char cmd, char * frameData, int frameDataLen) {
	char year, month, day, hour, minute, second;
	year = from_bcd(frameData[0]);
	month = from_bcd(frameData[1]);
	day = from_bcd(frameData[2]);
	hour = from_bcd(frameData[3]);
	minute = from_bcd(frameData[4]);
	second = from_bcd(frameData[5]);
	if ((year < 100) && (month < 13) && (day < 32) && (hour < 24)
			&& (minute < 60) && (second < 60)) {
		struct tm tGPS;
		tGPS.tm_year = (2000 - 1900) + year;
		tGPS.tm_mon = month - 1;
		tGPS.tm_mday = day;
		tGPS.tm_hour = hour;
		tGPS.tm_min = minute;
		tGPS.tm_sec = second;

		set_time(&tGPS);
		set_time2(&tGPS);
	}
}

void update_locomotiveTypeAndId(char *buffer) {
	char* cab_id = get_id();
	char tmp;
	buffer[8] = 0;
	tmp = buffer[3];
	buffer[3] = 0;
	int cab_type = atoi(buffer);
	buffer[3] = tmp;
	if(strcmp(get_cab_code(cab_type), "XXX") == 0)
    {
        sprintf(cab_id, "%d-%s", cab_type, buffer + 3);
    }
	else
    {
        sprintf(cab_id, "%s-%s", get_cab_code(cab_type), buffer + 3);
    }
}

static void process_control_frame(void *dataSrc, char *data, int len) {
	struct frame_manager *manager = get_frame_manager(CONTROL_MANAGER);
	struct frame sframe;
	struct frame * pframe;
	int length;
	char dest_addr = 0;
	char src_addr = 0;
	char operation = 0;
	char cmd = 0;
	char tmp;
	int i;
	char buffer[256];
	notReciveTimeCount = 0;
	struct tm time;
	set_sys_state(BIT5_MAIN_UNIT, STATE_MAINUNIT_OK);
	light_main_alarm(0);
	light_on(CONTROL_LED);
	for (i = 0; i < len; i++) {
		sframe.data[i] = data[i];
	}
	sframe.length = len;
	pframe = &sframe;
	dest_addr = data[6 + data[5]];
	src_addr = data[4];
	cmd = command_of_frame(pframe);
	operation = operation_of_frame(pframe);
	get_frame_real_data(pframe, buffer, &length);

	if (src_addr == MASTER_ADDRESS && dest_addr == RADIO_450M_ADDRESS
			&& (operation == 0x03) && (cmd == 0x20)) {
		update_locomotiveTypeAndId(buffer);
	} else if (src_addr == MASTER_ADDRESS && dest_addr == ALL_MMI_ADDRESS) {
		flushAllData();
	} else if (dest_addr == RECORD_ADDRESS && operation == 1) ////维护信息 需要应答的信息
			{
		tmp = 0;
		if (src_addr == 0x01) {
			tmp = 0x01;
		} else if ((src_addr == 0x03) || (src_addr == 0x04)) {
			tmp = 0x41;
		}
		send_frame(manager, RECORD_ADDRESS, src_addr, 1, tmp, pframe->data + 9,
				2);

		switch (cmd) {
		case (char) 0x33: //播放控制

			if (pframe->data[10] == (char) 0xff) {
				start_play(src_addr);
			} else if (pframe->data[10] == 0) {
				stop_play();
			}

			break;
		case (char) 0xfa: //问询测试
			buffer[0] = get_sys_state();
			int val = get_battery_volt();
			int byteIntPart = val / 1000;
			int byteDecimalPart = (val % 1000) / 10;
			buffer[1] = to_bcd(byteIntPart);
			buffer[2] = to_bcd(byteDecimalPart);
			printf("SysState:%x\r\n", buffer[0]);

			send_frame(manager, RECORD_ADDRESS, src_addr, 1, (char) 0xfb,
					buffer, 3);
			break;
		case (char) 0x34: //查询时钟

			get_time(&time);
			buffer[0] = to_bcd(time.tm_year - 100); //year
			buffer[1] = to_bcd(time.tm_mon + 1);
			buffer[2] = to_bcd(time.tm_mday);
			buffer[3] = to_bcd(time.tm_hour);
			buffer[4] = to_bcd(time.tm_min);
			buffer[5] = to_bcd(time.tm_sec);
			send_frame(manager, RECORD_ADDRESS, src_addr, 1, (char) 0x91,
					buffer, 6);

			break;
		case (char) 0x35: //设置时钟

			set_cir_time(dest_addr, src_addr, operation, cmd, buffer, length);

			break;

		case (char) 0xa5: //查询软件版本

			bcopy(version, buffer, 16);
			send_frame(manager, RECORD_ADDRESS, src_addr, 1, (char) 0xaa,
					buffer, 16);

			break;

		}

	} else if (dest_addr == RECORD_ADDRESS && operation == 3 && cmd == 0x46
			&& length >= 2 && buffer[0] == 0x03) //不需要应答
					{

		if (buffer[1] == 0x01) {
			set_sys_state(BIT0_POWER, STATE_POWER_ON);
		} else {
			set_sys_state(BIT0_POWER, STATE_POWER_OFF);
            set_poweroff(1);
		}

	} else {
		//do nothing;
	}

}

static void * proc_control(void *args) {
	while (1) {
		sleep(1);

		if (notReciveTimeCount < NOTRECICTTIMEMAX) {
			notReciveTimeCount++;
		} else {
			set_sys_state(BIT5_MAIN_UNIT, STATE_MAINUNIT_FAIL);
			light_main_alarm(1);
		}
	}
	return NULL;
}

void init_control_proc() {
	struct frame_manager *manager = get_frame_manager(CONTROL_MANAGER);
	manager->processHandler = process_control_frame;

}

void start_control_process() {
	init_control_proc();
	pthread_create(&thread_control, NULL, proc_control, NULL);
}

